<!--
 * @Author: 吴世扬
 * @Date: 2022-10-17 17:04:57
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2025-05-23 16:36:31
 * @FilePath: /vue3-admin/src/components/ui/Upload/PicsUpload.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<script setup lang="ts">
import { ref, computed } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { fileUpload } from '@/api/file';
import type { UploadResultData } from '@/typings/api/file';

import { getImageByToken } from '@/utils';

import type {
    UploadProps,
    UploadRawFile,
    UploadFile,
    UploadFiles,
    UploadRequestOptions
} from 'element-plus';

const props = withDefaults(
    defineProps<{
        tokens: (string | number | undefined)[];
        bucket?: string;
        remark?: string;
        limit?: number;
        disabled?: boolean;
        replace?: boolean; // 替换模式，只能上传一张，上传后会替换当前
    }>(),
    {
        tokens: () => [],
        bucket: '',
        remark: '',
        limit: 9,
        disabled: false,
        replace: false
    }
);

const emits = defineEmits<{
    (
        e: 'remove',
        data: {
            uploadFile: UploadFile;
            index: number;
            uploadFiles: UploadFiles;
        }
    ): void;
    (e: 'beforeUpload', data: UploadRawFile): void;
    (e: 'success', data: HttpResult<UploadResultData>[]): void;
    (e: 'change', files: File[], uploadFiles: any[]): void;
}>();

const dialogImageUrl = ref('');
const dialogVisible = ref(false);

const { tokens, remark, bucket } = toRefs(props);

const fileList = computed(() => {
    return tokens.value
        .filter((token) => token)
        .map((token, index) => {
            return {
                name: 'pic' + index,
                index,
                url: getImageByToken(token)
            };
        });
});

const handleUpload = (rawFile: UploadRawFile) => {
    emits('beforeUpload', rawFile);
};

/**
 * 删除
 * @param uploadFile
 * @param uploadFiles
 */
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
    emits('remove', {
        uploadFile,
        index: (uploadFile as any).index,
        uploadFiles
    });
};

/**
 *
 * @param uploadFile 预览
 */
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
    dialogImageUrl.value = uploadFile.url || '';
    dialogVisible.value = true;
};

const handleSuccess = (
    response: any,
    uploadFile: UploadFile,
    uploadFiles: UploadFiles
) => {
    if (uploadFiles.every((it) => it.status == 'success')) {
        emits(
            'success',
            uploadFiles
                .filter((item) => item.response)
                .map((item) => item.response as HttpResult<UploadResultData>)
        );
    }
};

let showProcess = ref(false);
let progress = ref(0);
// 更换头像
const changeFile = (file: any, fileLists: any) => {
    // if (props.replace) {
    //     if (fileLists.length > 1) {
    //         fileLists.splice(0, 1);
    //     }
    //     fileList = fileLists;
    // }
    // 文件上传进度条
    if (file.status === 'ready') {
        progress.value = 0;
        showProcess.value = true;
        const interval = setInterval(() => {
            if (progress.value >= 99) {
                clearInterval(interval);
                return;
            }
            progress.value += 1;
        }, 20);
    }
    if (file.status == 'success') {
        progress.value = 100;
        showProcess.value = false;
    }
};

const handleExceed = (files: File[], uploadFiles: any[]) => {
    ElMessage({
        type: 'error',
        message: `最多上传${props.limit}张图片`
    });
};
const handleRequest = (options: UploadRequestOptions) => {
    const rawFile = options.file;
    let type = 99;
    if (
        rawFile.type.indexOf('jpeg') !== -1 ||
        rawFile.type.indexOf('png') !== -1 ||
        rawFile.type.indexOf('jpg') !== -1
    ) {
        type = 1;
    } else if (rawFile.type.indexOf('video') !== -1) {
        type = 2;
    } else {
        type = 99;
    }
    return fileUpload({
        bucket: bucket.value,
        remark: remark.value,
        type,
        file: options.file
    });
};
</script>

<template>
    <div class="picupload-container">
        <el-upload
            :file-list="fileList"
            list-type="picture-card"
            accept="image/*"
            :limit="props.limit"
            :before-upload="handleUpload"
            :on-preview="handlePictureCardPreview"
            :on-remove="handleRemove"
            :on-exceed="handleExceed"
            :http-request="handleRequest"
            multiple
            :on-success="handleSuccess"
            :disabled="disabled"
            :on-change="changeFile"
        >
            <el-icon><Plus /></el-icon>
        </el-upload>

        <el-progress v-if="showProcess" :percentage="progress" />
        <el-dialog v-model="dialogVisible">
            <div>
                <img
                    style="width: 100%"
                    :src="dialogImageUrl"
                    alt="Preview Image"
                />
            </div>
        </el-dialog>
    </div>
</template>

<style lang="scss" scoped>
:deep(.el-upload-list__item) {
    width: 100px;
    height: 100px;
}

:deep(.el-upload) {
    width: 100px;
    height: 100px;
}
</style>
